package service

import (
	"context"
	"github.com/gofrs/uuid"
	"go-demo/domain"
	"go-demo/util"
)

type DemoDto struct {
	Id     string         `json:"id"`     //主键
	BillNo string         `json:"billNo"` //单号
	Items  []*DemoItemDto `json:"items"`  //明细
}

type DemoItemDto struct {
	Id     string `json:"id"`     //主键
	DemoId string `json:"demoId"` //Demo主键
	ItemNo string `json:"itemNo"` //编码
}

type GetListDemoInput struct {
	PageAndSortRequest
	BillNo string `form:"billNo" `
	ItemNo string `form:"itemNo"`
}

type GetListDemoOutput struct {
	PageResponse
	Items []*DemoDto `json:"items"`
}

type CreateDemoInput struct {
	BillNo string `json:"billNo"`
	Items  []*struct {
		ItemNo string `json:"itemNo"`
	} `json:"items"`
}

type DemoAppService struct {
	uow            *domain.UnitOfWork
	demoRepository *domain.DemoRepository
}

func NewDemoAppService(uow *domain.UnitOfWork, demoRepository *domain.DemoRepository) *DemoAppService {
	return &DemoAppService{uow, demoRepository}
}

func (s *DemoAppService) GetList(ctx context.Context, input *GetListDemoInput) (output *GetListDemoOutput, code int, err error) {
	//获取列表
	list, count, err := s.demoRepository.GetList(ctx, input.BillNo, input.ItemNo, input.PageIndex, input.PageSize)
	if err != nil {
		return nil, util.StatusErr, err
	}

	//装载DTO
	if len(list) > 0 {
		output.Items = make([]*DemoDto, 0)
		for _, v := range list {
			output.Items = append(output.Items, demoMapToDto(v))
		}
	}
	output.TotalCount = count

	return output, util.StatusOk, err
}

func (s *DemoAppService) Create(ctx context.Context, input *CreateDemoInput) (*DemoDto, int, error) {
	output := new(DemoDto)
	code := util.StatusOk
	if err := s.uow.Do(ctx, nil, func(store domain.UnitOfWorkStore) error {

		//生成id
		demoId, err := uuid.NewV1()
		if err != nil {
			return err
		}

		//初始化demo
		demo, err := domain.NewDemo(demoId.String(), input.BillNo)
		if err != nil {
			return err
		}

		for _, v := range input.Items {

			//生成明细id
			itemId, err := uuid.NewV1()
			if err != nil {
				return err
			}

			//添加行项目
			err = demo.AddItem(itemId.String(), v.ItemNo)
			if err != nil {
				return err
			}
		}

		//添加demo和demoitem
		if err = store.Demo().Insert(ctx, demo); err != nil {
			return err
		}

		output = demoMapToDto(demo)

		return nil
	}); err != nil {
		return nil, util.StatusErr, err
	}
	return output, code, nil
}

func (s *DemoAppService) Delete(ctx context.Context, id string) (int, error) {
	if err := s.uow.Do(ctx, nil, func(store domain.UnitOfWorkStore) error {
		if err := store.Demo().Delete(ctx, id); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return util.StatusErr, err
	}
	return util.StatusOk, nil
}

func demoMapToDto(entity *domain.Demo) *DemoDto {
	dto := &DemoDto{
		Id:     entity.Id,
		BillNo: entity.BillNo,
		Items:  make([]*DemoItemDto, 0),
	}
	for _, v := range entity.Items {
		dto.Items = append(dto.Items, &DemoItemDto{
			Id:     v.Id,
			DemoId: v.DemoId,
			ItemNo: v.ItemNo,
		})
	}
	return dto
}
